/* ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
*
* AION - sterownik czasowo temperaturowy
* http://code.google.com/p/aions
*
* Copyright (C) 2014 Piotr Murawski
*
* Niniejszy program jest wolnym oprogramowaniem; mozesz go
* rozprowadzac dalej i/lub modyfikowac na warunkach Powszechnej
* Licencji Publicznej GNU, wydanej przez Fundacje Wolnego
* Oprogramowania - wedlug wersji 3-ciej tej Licencji lub którejs
* z pozniejszych wersji.
*
* Autor, NIE UDZIELA zgody na wykorzystanie, calosci lub jakiej
* kolwiek czesci niniejszego oprogramowania, czy to w postaci
* kodu zrodlowego czy tez, bibliotek, plikow wykonywalnych czy tez
* innej formy pochodnej plikow zrodlowych do CELOW KOMERCYJNYCH.
*
* Niniejszy program rozpowszechniany jest z nadzieja iz bedzie on
* uzyteczny - jednak BEZ JAKIEJKOLWIEK GWARANCJI, nawet domyslnej
* gwarancji PRZYDATNOSCI HANDLOWEJ albo PRZYDATNOSCI DO OKRESLONYCH
* ZASTOSOWAN. W celu uzyskania blizszych informacji - Powszechna
* Licencja Publiczna GNU.
*
* Z pewnoscia wraz z niniejszym programem otrzymales tez egzemplarz
* Powszechnej Licencji Publicznej GNU (GNU General Public License);
* jesli nie - napisz do Free Software Foundation, Inc., 675 Mass Ave,
* Cambridge, MA 02139, USA.
*
* Powszechna Licencja GNU znajduje sie w zalaczonym pliku:
* Licencja.txt
*
* Powszechna Licencja GNU dostepna jest rowniez na stronie:
* http://www.gnu.org/licenses/licenses.html
*
* nieoficjalne polskie tlumaczenie na
* http://www.gnu.org.pl
*
* ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
*
* AION - time temperature controller
* http://code.google.com/p/aions
*
* Copyright (C) 2014 Piotr Murawski
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Autor, doea not allow to use this software, as whole or in parts, in form 
* of source code or compiled code for COMMERCIAL USE.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
*/


   #include  <stdio.h>
   #include  <stdarg.h>

   #include  "FreeRTOS.h"
   #include  "task.h"
   #include  "queue.h"
   #include  "message.h"

   #include  "91x_scu.h"
   #include  "91x_enet.h"
   #include  "91x_vic.h"
   #include  "91x_tim.h"
   #include  "91x_gpio.h"
   #include  "91x_emi.h"
   #include  "91x_ssp.h"
   #include  "91x_wdg.h"

   #include  "types.h"
   #include  "board.h"
   #include  "errors.h"
   #include  "os_items.h"
   #include  "console.h"
   #include  "hw_config.h"
   #include  "os_printf.h"
   #include  "terminal.h"
   #include  "status.h"
   #include  "params.h"
   #include  "net_dma.h"
   #include  "net_ip.h"
   #include  "temperatury.h"
   #include  "stack_dbg.h"
   #include  "lcd_hw.h"
   #include  "adc.h"
   #include  "konsola.h"

   //-------------------------------------------------
   // Tasks Handles
   //-------------------------------------------------
   xTaskHandle TASK_Terminal;
   xTaskHandle TASK_NetRxDma;
   xTaskHandle TASK_OsPrintf;
   xTaskHandle TASK_Manager;
   xTaskHandle TASK_PhyStatus;
   xTaskHandle TASK_UipProc;

   xTaskHandle TASK_Temperatury;
   xTaskHandle TASK_Lcd;
   xTaskHandle TASK_Sterowanie;
   xTaskHandle TASK_Logger;
   xTaskHandle TASK_Scheduler;
   xTaskHandle TASK_Krzywe;
   
   int MAIN_Cpsr;
   int MAIN_Sp;
   U32 MAIN_SysTick;
   U16 MAIN_Kreciolek;
   static VU32 idletask;
   U8  MAIN_UartPanel = 0;
   VU8 MAIN_ProgramSekundowy = 0;
   VU8 MAIN_UsePhaseReg = 0;
   VU32 MAIN_Dbg;

   
   void NET_Init(U8 resatart);
   void MAIN_StartWatchdog(void);
   U32 Asm_CpuRegs(int* p_cpsr, int* p_sp);   



   #define LC_KRECIOL_BURNS  (0x80)

//=============================================================
//  main
//        main C function, C code start
//  INPUT
//        void
//  RETURN
//        void
//=============================================================
int a_main(void)
{
   GPIO_InitTypeDef lvPinCfg;
   portBASE_TYPE    lvRes;

   STAT_SecInts=0;
   
   //----------------------------------------------------------------
   // Manage reset source
   //----------------------------------------------------------------
   //IF(watchdog reset)
   if(SCU_GetFlagStatus(SCU_FLAG_WDG_RST)==SET)
   {
      STAT_WdgResetCounter++;
      SCU_ClearFlag(SCU_FLAG_WDG_RST);
   }else{
      STAT_WdgResetCounter=0;
   }
   //----------------------------------------------------------------

   //configure some HW stuff, e.g. PLLs and other clocks
   HWCF_ConfigureBoard();

   SCU_APBPeriphClockConfig(__GPIO7,ENABLE);
   SCU_APBPeriphReset(__GPIO7,DISABLE);
   SCU_APBPeriphClockConfig(__GPIO3,ENABLE);
   SCU_APBPeriphReset(__GPIO3,DISABLE);
   lvPinCfg.GPIO_Type        =GPIO_Type_PushPull;
   // GUZ1
   lvPinCfg.GPIO_Pin         =0x40;
   lvPinCfg.GPIO_Direction   =GPIO_PinInput;
   lvPinCfg.GPIO_Alternate   =GPIO_InputAlt1;
   lvPinCfg.GPIO_IPConnected =GPIO_IPConnected_Disable;
   GPIO_Init(GPIO3,&lvPinCfg);

   TEMPR_ConsoleTookPort=0;
   CONS_Enabled = 0;

   if(((GPIO3->DR[0xC0<<2])>>6)&1){
	   CONS_Enabled = 0;
       TEMPR_ConsoleTookPort=0;
   }else{
	   CONS_Enabled = 1;
       TEMPR_ConsoleTookPort=1;
   }
   if(((GPIO3->DR[0xC0<<2])>>7)&1){
	   MAIN_Kreciolek =0;
   }else{
	   MAIN_Kreciolek =1;
   }

   //----------------------------------------
   // check, if UART LCD Panel is in use
   //----------------------------------------
   // Port 2.3 - RW, Panel kiedy = 0
   SCU_APBPeriphClockConfig(__GPIO2,ENABLE);
   SCU_APBPeriphReset(__GPIO2,DISABLE);
   lvPinCfg.GPIO_Pin         =GPIO_Pin_3;
   lvPinCfg.GPIO_Direction   =GPIO_PinInput;
   lvPinCfg.GPIO_Alternate   =GPIO_InputAlt1;
   lvPinCfg.GPIO_IPConnected =GPIO_IPConnected_Disable;
   GPIO_Init(GPIO2,&lvPinCfg);
   if((GPIO2->DR[GPIO_Pin_3<<2] & GPIO_Pin_3) == 0){
	   if((CONS_Enabled==0))
	   {
			MAIN_UartPanel = 1;
			TEMPR_ConsoleTookPort=1;
			//wyslanie znaku QK(G) po odczytaniu ustawien z parameterow
	   }
   }
   //----------------------------------------


   COL_RESET;

   COL_BLUE;
   uprintf("\n\r");
   COL_GREEN;
   uprintf("<*> AION <*> AION <*> AION <*>\n\r");
   uprintf("\n\r");

   //-----------------------------------------------------------------------
   // some HW pins  
   //-----------------------------------------------------------------------
   SCU_APBPeriphClockConfig(__GPIO4,ENABLE);
   SCU_APBPeriphReset(__GPIO4,DISABLE);
   SCU_APBPeriphClockConfig(__GPIO5,ENABLE);
   SCU_APBPeriphReset(__GPIO5,DISABLE);
   SCU_APBPeriphClockConfig(__GPIO6,ENABLE);
   SCU_APBPeriphReset(__GPIO6,DISABLE);
   SCU_APBPeriphClockConfig(__GPIO8,ENABLE);
   SCU_APBPeriphReset(__GPIO8,DISABLE);
   SCU_APBPeriphClockConfig(__GPIO9,ENABLE);
   SCU_APBPeriphReset(__GPIO9,DISABLE);
   SCU_APBPeriphClockConfig(__WIU,ENABLE);
   SCU_APBPeriphClockConfig(__RTC,ENABLE); /*enable RTC clock*/
   SCU_APBPeriphReset(__RTC,DISABLE);      /*RTC out of RESET state*/
   
   //GPIO_EMIConfig(DISABLE);
   
   PARM_ParametersInit();
   
   MAIN_Kreciolek|=PARM_Params.kreciolek;
   if(PARM_Params.boardtype == CONFIG_BOARD_QUOTEK1_0){
        MAIN_Kreciolek|=LC_KRECIOL_BURNS;
   }

   if(MAIN_UartPanel){
	   LCDHW_sendInit(MAIN_Kreciolek);
   }

   uprintf("%d\n\r",sizeof(PARM_Params));
   
   NET_Init(0);
   
//  //UART 1 TX P3.3 
//  lvPinCfg.GPIO_Pin         =GPIO_Pin_3;
//  lvPinCfg.GPIO_Direction   =GPIO_PinInput;
//  lvPinCfg.GPIO_Type        =GPIO_Type_PushPull;
//  lvPinCfg.GPIO_IPConnected =GPIO_IPConnected_Disable;
//  lvPinCfg.GPIO_Alternate   =GPIO_InputAlt1;
//  GPIO_Init(GPIO3,&lvPinCfg);

   //---------------------------------------------------------------
   // Cerate tasks
   //---------------------------------------------------------------

   //OsPrintf
   lvRes=xTaskCreate(OSPRN_TA_OsPrintf,
                     "OsPrintf",
                     256,
                     NULL,
                     TASK_PRIO_OSPRINTF,
                     (xTaskHandle *) &TASK_OsPrintf);
   ASSERT(pdPASS!=lvRes);


   //Terminal
   if(CONS_Enabled){
	   lvRes=xTaskCreate(TERM_TA_Terminal,
						 "Terminal",
						 256,
						 NULL,
						 TASK_PRIO_TERMINAL,
						 (xTaskHandle *) &TASK_Terminal);
	   ASSERT(pdPASS!=lvRes);
   }

//   //NetRxDma
//   lvRes=xTaskCreate(NDMA_TA_RxDma,
//                     "NetDmaRx",
//                     256,
//                     NULL,
//                     TASK_PRIO_NETDMA,
//                     (xTaskHandle *) &TASK_NetRxDma);
//   ASSERT(pdPASS!=lvRes);
   
   //UIP process task
   lvRes=xTaskCreate(NETI_TA_UipProc,
                     "uIP_proc",
                     300,
                     NULL,
                     TASK_PRIO_UIPPROC,
                     (xTaskHandle *) &TASK_UipProc);
   ASSERT(pdPASS!=lvRes);

   
   //PhyStatus
   lvRes=xTaskCreate(NDMA_TA_PhyStatus,
                     "PhyStatus",
                     256,
                     NULL,
                     TASK_PRIO_PHYSTATUS,
                     (xTaskHandle *) &TASK_PhyStatus);
   ASSERT(pdPASS!=lvRes);

   //Manager
   lvRes=xTaskCreate(MNGM_TA_Manager,
                     "Manager",
                     400,
                     NULL,
                     TASK_PRIO_MANAGER,
                     (xTaskHandle *) &TASK_Manager);
   ASSERT(pdPASS!=lvRes);
   //***********************
   // temperatury
   lvRes=xTaskCreate(TEMPR_TA_Temperatury,
                     "Temperat",
                     400,
                     NULL,
                     TASK_PRIO_TEMPERATURY,
                     (xTaskHandle *) &TASK_Temperatury);
   ASSERT(pdPASS!=lvRes);
   //***********************
   // LCD
   lvRes=xTaskCreate(DISPL_TA_Lcd,
                     "LCD",
                     400,
                     NULL,
                     TASK_PRIO_TEMPERATURY,
                     (xTaskHandle *) &TASK_Lcd);
   ASSERT(pdPASS!=lvRes);
   //***********************
   // sterowanie
   lvRes=xTaskCreate(STER_TA_PetlaSterujaca,
                     "Sterowan",
                     400,
                     NULL,
                     TASK_PRIO_STEROWANIE,
                     (xTaskHandle *) &TASK_Sterowanie);
   ASSERT(pdPASS!=lvRes);
   //***********************
   // Logger
   lvRes=xTaskCreate(LOG_TA_Logger,
                     "Logger",
                     220,
                     NULL,
                     TASK_PRIO_LOGGER,
                     (xTaskHandle *) &TASK_Logger);
   ASSERT(pdPASS!=lvRes);
   //***********************
   // scheduler
   lvRes=xTaskCreate(SCHED_TA_Scheduler,
                     "Schedul",
                     256,
                     NULL,
                     TASK_PRIO_SCHEDULER,
                     (xTaskHandle *) &TASK_Scheduler);
   ASSERT(pdPASS!=lvRes);
   //***********************
   // krzywe
   lvRes=xTaskCreate(TEMPR_TA_Krzywe,
                     "Krzywe",
                     1200/4,
                     NULL,
                     TASK_PRIO_KRZYWE,
                     (xTaskHandle *) &TASK_Krzywe);
   ASSERT(pdPASS!=lvRes);

   

   STACK_Init(); 
   STACK_AddOsStack("OS Print",TASK_OsPrintf);
   STACK_AddOsStack("Terminal",TASK_Terminal);
   //STACK_AddOsStack("NetDMA  ",TASK_NetRxDma);
   STACK_AddOsStack("Uip Proc",TASK_UipProc);
   STACK_AddOsStack("PHY Stat",TASK_PhyStatus);
   STACK_AddOsStack("manager ",TASK_Manager);
   STACK_AddOsStack("Temperat",TASK_Temperatury);
   STACK_AddOsStack("LCD     ",TASK_Lcd);
   STACK_AddOsStack("Sterowan",TASK_Sterowanie);
   STACK_AddOsStack("Logger  ",TASK_Logger);
   STACK_AddOsStack("Schedule",TASK_Scheduler);
   STACK_AddOsStack("Krzywe  ",TASK_Krzywe);
   
   Asm_CpuRegs(&MAIN_Cpsr, &MAIN_Sp);

   KPRINTF("MAIN: about to start FreeRTOS ... \n\r");
   vTaskStartScheduler();

   //never beeing here, thus assert
   ASSERT(1);

   return(0);
}


void NET_Init(U8 resatart)
{
    //Enable the whole MAC/PHY path (clocks, etc.)
    if(!resatart) ENET_InitClocksGPIO();

    ENET_Init();

    //start it
    ENET_Start();

    //set MAC address
    ENET_MAC->MAL =(NETI_CFG_MACADDRESS4 << 24 ) |
                   (NETI_CFG_MACADDRESS3 << 16 ) |
                   (NETI_CFG_MACADDRESS2 << 8 )  |
                   (NETI_CFG_MACADDRESS1);

    ENET_MAC->MAH =(NETI_CFG_MACADDRESS6 <<8 )   |
                   (NETI_CFG_MACADDRESS5);

    //-------------------------
    //configure interrupts
    //-------------------------
    //clear pending interrupts
    ENET_DMA->ISR = 0;
    //enable TX_CURR_DONE at MAC level
    ENET_DMA->IER = (vu32)(1 << 31);

    //-------------------------
    //Disable MAC addr filter 
    //-------------------------    
    //ENET_MAC->MCR |=MAC_MCR_RA | (4 << 17); 
    
    NDMA_DisableRx();
}




void MAIN_StartWatchdog(void)
{
   WDG_InitTypeDef lvWdgInit;

   SCU_APBPeriphClockConfig(__WDG,ENABLE);
   WDG_DeInit();
   WDG_StructInit(&lvWdgInit);
   lvWdgInit.WDG_Mode        =WDG_Mode_Wdg;
   lvWdgInit.WDG_ClockSource =WDG_ClockSource_Rtc; //32768 Hz
   //reset every 1 sek
   lvWdgInit.WDG_Prescaler   =4;
   lvWdgInit.WDG_Preload     =32768;
   WDG_Init(&lvWdgInit);
   WDG_Cmd(ENABLE);
}





//Custom IDLE task
void vApplicationIdleHook( void )
{
  while(1)
  {
    idletask++;
  };
}



void vApplicationTickHook( void )
{
   static VU32 lv_Tick=0;
   static TMessage lvMes;
   static U32 lvTemperatureTick=0;
   static U32 lvTickCnt=0;
   static U32 lvMinute;
   static U32 lvTick100=0;
   static U32 lvLastGuz=0xF;
   static U32 lvGuz;
   static U32 kPipe;
   static U8  kLast;
   static U8  guzDelay = 0;
   static U16 adcTick = 0;
   
   lv_Tick++;
   lvTickCnt++;
   lvTick100++;
   MAIN_SysTick++;

   if((lv_Tick==1) || (lv_Tick==500))
   {       
       lvMes.Message=MES_IP_TIMER;
       xQueueSendFromISR(NETI_QH_UipMsg,&lvMes,pdFALSE);
   }
      
   if(lv_Tick==1000)
   {
       lv_Tick=0;
       STAT_SecInts++;       
       lvMes.Message=MES_STER_1SEKTIMER;
       xQueueSendFromISR(STER_QH_Ster,&lvMes,pdFALSE);
       lvMes.Message=MES_MGR_1SEKTIMER;
       xQueueSendFromISR(MNGM_QH_Manager,&lvMes,pdFALSE);
       lvMinute++;
       if(lvMinute==60){
          lvMinute=0;
       }
       //send message every half minute
       if((lvMinute==0)||(lvMinute==30)){
           lvMes.Message=MES_SCHED_PERIOD30SEK;
           xQueueSendFromISR(SCHED_QH_Logger,&lvMes,pdFALSE);
       }       
   }else if((lv_Tick==400) && (MAIN_ProgramSekundowy)){
	   // 1sek tick to scheduler
       lvMes.Message=MES_SCHED_PERIOD1SEK;
       xQueueSendFromISR(SCHED_QH_Logger,&lvMes,pdFALSE);
   }
   
   if(lvTick100==100){
       lvTick100=0;
       lvMes.Message=MES_STER_100MSTIMER;
       xQueueSendFromISR(STER_QH_Ster,&lvMes,pdFALSE);
   }


   if(ADC_Active){
	   adcTick++;
	   if(adcTick==200){
		  adcTick=0;
		  if(ADC_Cycle == 0){
			  //start ADC conversion
			  ADC->CR = ADC->CR | 1;
		  }else{
			   lvMes.Message=MES_TEMPERATURA_ADCCYCLE;
			   lvMes.Sender = ADC_Cycle;
			   xQueueSendFromISR(TEMPR_QH_Temper,&lvMes,pdFALSE);
		  }
	   }
   }   
   
   //miezenie temperatury co 700ms. 
   lvTemperatureTick++;
   if(lvTemperatureTick==TEMPR_MESUREPERIOD){
       lvMes.Message=MES_TEMPERATURA_PERIOD;
       xQueueSendFromISR(TEMPR_QH_Temper,&lvMes,pdFALSE);
       lvTemperatureTick=0;
   }
   
   //----------------------------------------------------
   // odsiwerzanie guzikow
   //----------------------------------------------------
   if(guzDelay) guzDelay--;
   if(((lvTickCnt&0x1)==0) && (!MAIN_UartPanel)){
       lvGuz = (GPIO7->DR[0xC0<<2])>>6;
       lvGuz|= (GPIO3->DR[0xC0<<2])>>4;
       lvGuz^=0x0F;
       //IF(kreciolek)
       if(MAIN_Kreciolek){
    	   if(kLast!=(lvGuz & 0x3)){
			   kPipe<<=8;
			   kPipe|=lvGuz & 0x3;
			   kPipe&=0x00FFFFFF;
    	       kLast=lvGuz & 0x3;
   		       lvGuz&=0x0C;
   		       //IF kreciol burns
   		       if(MAIN_Kreciolek & LC_KRECIOL_BURNS){
   		    	   if(guzDelay == 0){
					   //IF w gore
					   if(kPipe==0x00020001){
						   if(MAIN_Kreciolek & CONFIG_KRECIOL_CCW) lvGuz|=1;
						   else                                    lvGuz|=2;
					   }else
					   if(kPipe==0x00010002){
						   if(MAIN_Kreciolek & CONFIG_KRECIOL_CCW) lvGuz|=2;
						   else                                    lvGuz|=1;
					   }
   		    	   }
   		       }else{
   		    	   //stary kreciol
				   if(kPipe==0x00000203){
					   if(MAIN_Kreciolek & CONFIG_KRECIOL_CCW) lvGuz|=2;
					   else                                    lvGuz|=1;
				   }else
				   if(kPipe==0x00000302){
					   if(MAIN_Kreciolek & CONFIG_KRECIOL_CCW) lvGuz|=1;
					   else                                    lvGuz|=2;
				   }
   		       }
    	   }else{
   		       lvGuz&=0x0C;
    	   }
       }
       if((lvLastGuz!=lvGuz)&&(lvGuz)){
          lvMes.Message=MES_REFRESH_GUZIKI;
          lvMes.Sender=lvGuz;
          xQueueSendFromISR(DISPL_QH_Lcd,&lvMes,pdFALSE);
          guzDelay = 40;
       }
       lvLastGuz=lvGuz;
   }else
   if(MAIN_UartPanel){
	   if(LCDHW_PanleGuzBufIn != LCDHW_PanleGuzBufOut){
          lvMes.Message=MES_REFRESH_GUZIKI_UPANEL;
          xQueueSendFromISR(DISPL_QH_Lcd,&lvMes,pdFALSE);
	   }
   }

   if((MAIN_SysTick & 0xFF) == 0){
      lvMes.Message=MES_REFRESH_LCD_TIMER_FAST;
      xQueueSendFromISR(DISPL_QH_Lcd,&lvMes,pdFALSE);
   }
}












/*---------------------------------- End of File -----------------------------*/
